<?php

/**
 * Created by PhpStorm.
 * User: meiyun1
 * Date: 2017/2/24
 * Time: 上午11:39
 */

namespace App\App\Services\Web;

use App\Contracts\Repositories\ActivityRepository;
use App\Contracts\Services\Storage\StorageService;
use App\Models\ActivityModel\ActivityModelService;
use App\Models\ActivityModelTemplate\ActivityModelTemplateService;
use App\Models\ActivityPrize\ActivityPrizeService;
use App\Models\ActivityRecord\ActivityRecordService;
use App\Models\PrizeRecord\PrizeRecordService;
use App\Models\Activity\ActivityService as ActivityDomainService;
use App\Models\VoteCandidate\VoteCandidateService;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use App\Morefun\Wechat\Service as WechatService;

class ActivityService
{
    /**
     * @var ActivityDomainService
     */
    private $activityService;

    /**
     * @var ActivityModelService
     */
    private $modelService;

    /**
     * @var ActivityModelTemplateService
     */
    private $tplService;

    /**
     * @var PrizeRecordService
     */
    private $prizeRecodeService;

    /**
     * @var ActivityPrizeService
     */
    private $activityPrizeService;

    /**
     * @var UserService
     */
    private $userService;

    /**
     * @var ActivityRecordService
     */
    private $activityRecordsService;

    /**
     * @var StorageService
     */
    private $storageService;

    /**
     * @var ActivityRepository
     */
    private $activityRepository;

    private $voteCandidateService;

    /**
     * @var WechatService
     */
    private $wechatService;

    public function __construct(
        ActivityDomainService $activityService,
        ActivityModelService $modelService,
        ActivityModelTemplateService $modelTemplateService,
        PrizeRecordService $prizeRecordService,
        ActivityPrizeService $activityPrizeService,
        UserService $userService,
        ActivityRecordService $activityRecordService,
        StorageService $storageService,
        ActivityRepository $activityRepository,
        VoteCandidateService $voteCandidateService,
        WechatService $wechatService
    )
    {
        $this->activityService = $activityService;
        $this->modelService = $modelService;
        $this->tplService = $modelTemplateService;
        $this->prizeRecodeService = $prizeRecordService;
        $this->activityPrizeService = $activityPrizeService;
        $this->userService = $userService;
        $this->activityRecordsService = $activityRecordService;
        $this->storageService = $storageService;
        $this->activityRepository = $activityRepository;
        $this->voteCandidateService = $voteCandidateService;
        $this->wechatService = $wechatService;
    }

    public function createActivity($data)
    {
        return $this->activityService->createActivity($data);
    }

    public function findOne($id)
    {
        return $this->activityService->findOne($id);
    }

    public function saveActivity($data, $id)
    {
        return $this->activityService->saveActivityById($data, $id);
    }

    public function deleteActivity($ids)
    {
        return $this->activityService->deleteActivity($ids);
    }

    public function getModelTemplates()
    {
        $models = $this->modelService->findAll();
        $tpls = $this->tplService->findByModel();
        $data[] = [
            'model_id'   => '',
            'model_name' => '全部',
            'tpls'       => $tpls,
        ];

        foreach ($models as $row) {
            $tps = [];
            foreach ($tpls as $tp) {
                $tp->model;
                if ($row->id == $tp->model_id) {
                    $tps[] = $tp;
                }
            }
            $data[] = [
                'model_id'   => $row->id,
                'model_name' => $row->name,
                'tpls'       => $tps,
            ];
        }

        return $data;
    }

    public function getActivitiesByUser($user_id)
    {
        return $this->activityService->getActivityByUser($user_id);
    }

    /**
     * @param int         $category
     * @param int         $start
     * @param int         $limit
     * @param string      $sort
     * @param string      $order
     * @param string|null $keyword
     *
     * @return array
     */
    public function getActivityListByPage($category, $start, $limit, $sort, $order, $keyword = null)
    {
        $groupCode = $this->userService->getGroupCode();

        return $this->activityRepository->findByCategory($groupCode, $category, $sort, $order, $start, $limit, $keyword);
    }

    /**
     * 新建活动，更新活动，删除活动调用
     *
     * @param $activity_id
     *
     */
    public function updateActivityPrizeRecord($activity_id)
    {
        $activity = $this->activityService->findOne($activity_id);
        if (!empty($activity)) {
            $activity_prize_records = $this->prizeRecodeService->findListByConditions([['activity_id', $activity_id]]);
            $prize_ids = $activity_prize_records->pluck('prize_id');
            $prizes = $activity->prizes;
            $new_prize_ids = $prizes->pluck('prize_id');
            $diffPrizeIds = $prize_ids->diff($new_prize_ids);
            foreach ($diffPrizeIds->all() as $pri_id) {
                $lastPrizeRecord = $this->prizeRecodeService->getLastOne([['prize_id', $pri_id]]);
                if (!empty($lastPrizeRecord)) {
                    $history_record = $activity_prize_records->where('prize_id', $pri_id)->first()->toArray();
                    $record = [
                        'prize_id'    => $pri_id,
                        'activity_id' => $activity_id,
                        'limit'       => $history_record['limit'],
                        'number'      => $history_record['number'],
                        'summary'     => $lastPrizeRecord['summary'] + $history_record['number'],
                        'probability' => $history_record['probability'],
                        'operate'     => 'entry',
                    ];
                    $this->prizeRecodeService->create($record);
                    $activity_prize_records->where('prize_id', $pri_id)->first()->delete();
                }
            }
            foreach ($prizes->toArray() as $row) {
                if (!$prize_ids->contains($row['prize_id'])) {
                    $lastPrizeRecord = $this->prizeRecodeService->getLastOne([['prize_id', $row['prize_id']]]);

                    if (!empty($lastPrizeRecord)) {
                        $record = [
                            'prize_id'    => $row['prize_id'],
                            'activity_id' => $activity_id,
                            'limit'       => $row['winning_limit'],
                            'number'      => $row['surplus'],
                            'probability' => $row['winning_probability'],
                            'summary'     => $lastPrizeRecord['summary'] - $row['surplus'],
                            'operate'     => 'delivery',
                        ];
                        $this->prizeRecodeService->create($record);
                    }
                } else {
                    $localPrizeRecord = $this->prizeRecodeService->findListByConditions([['activity_id', $activity_id], ['prize_id', $row['prize_id']]])->first();
                    $lastPrizeRecord = $this->prizeRecodeService->getLastOne([['prize_id', $row['prize_id']]]);
                    if ($localPrizeRecord->operate == 'delivery') {
                        $localPrizeRecord->summary = $lastPrizeRecord['summary'] - ($row['surplus'] - $localPrizeRecord->number);
                        $localPrizeRecord->number = $row['surplus'];
                        $localPrizeRecord->save();
                    } else {
                        $localPrizeRecord->operate = 'delivery';
                        $localPrizeRecord->summary = $lastPrizeRecord['summary'] - $row['surplus'];
                        $localPrizeRecord->number = $row['surplus'];
                        $localPrizeRecord->save();
                    }
                }
            }
        } else {
            $prizes = $this->activityPrizeService->findList([['activity_id', $activity_id]])->toArray();
            foreach ($prizes as $row) {
                $lastPrizeRecord = $this->prizeRecodeService->getLastOne([['prize_id', $row['prize_id']]]);
                if (!empty($lastPrizeRecord)) {
                    $record = [
                        'prize_id'    => $row['prize_id'],
                        'activity_id' => $activity_id,
                        'limit'       => $row['winning_limit'],
                        'number'      => $row['surplus'],
                        'probability' => $row['winning_probability'],
                        'operate'     => 'entry',
                    ];
                    $record['summary'] = $lastPrizeRecord['summary'] + $row['surplus'];
                    $this->prizeRecodeService->create($record);
                }
            }
        }
    }

    public function countByConditions($conditions)
    {
        return $this->activityService->countByConditions($conditions);
    }

    public function findByUserAndRunning($userId)
    {
        return $this->activityService->findByUserAndRunning($userId);
    }

    public function getActivityPrizeStock($activity_id)
    {
        $activityPrizes = $this->activityPrizeService->findList([['activity_id', $activity_id]]);
        foreach ($activityPrizes as &$row) {
            $row->prize;
            $row->awarding_number = $this->activityRecordsService->count([['activity_id', $activity_id], ['prize_id', $row->prize_id], ['is_exchange', 1]]);
            $row->not_awarding_number = $this->activityRecordsService->count([['activity_id', $activity_id], ['prize_id', $row->prize_id], ['is_exchange', 0]]);
            //$row->surplus = $row->stock_limit -($row->awarding_number +$row->not_awarding_number);
        }
        unset($row);

        return $activityPrizes;
    }

    public function getActivityByGroup($groupCode)
    {
        $activities = $this->activityService->getActivityByGroup($groupCode);
        if ($activities) {
            foreach ($activities as $index => $activity) {
                if (!$activity->appIsOpen()) {
                    unset($activities[$index]);
                    continue;
                }
                $activity->wechatUrl = '';
                if ($activity->wechatIsOpen()) {
                    $activity->wechatUrl = $this->wechatService->makeSilentlyAuthorizedUrl($activity->getId());
                }
                $activity->model;
                $activity->template;
                if (!empty($activity->listBackgroundImg)) {
                    $activity->listBackgroundImg = $this->storageService->toHttpUrl($activity->listBackgroundImg);
                }
                if (!empty($activity->shares)) {
                    $shares = \GuzzleHttp\json_decode($activity->shares, true);
                    if (isset($shares['icon']) && !empty($shares['icon'])) {
                        $shares['icon'] = $this->storageService->toHttpUrl($shares['icon']);
                    }
                    if (isset($shares['thumb']) && !empty($shares['thumb'])) {
                        $shares['thumb'] = $this->storageService->toHttpUrl($shares['thumb']);
                    }
                    $activity->shares = \GuzzleHttp\json_encode($shares);
                }
                $activities[$index] = $activity;
            }
        }

        return $activities;
    }

    public function getGroupActivityByType($groupCode, $hostUrl)
    {
        $activityService = $this->activityService;
        $activities = $activityService->getActivityByGroup($groupCode);
        $activityData = [];
        $categoryData = [];

        if ($activities) {
            foreach ($activities as $index => $activity) {
                if (!$activity->appIsOpen()) {
                    unset($activities[$index]);
                    continue;
                }
                $types = $activityService::ACTIVITY_TYPE;
                $rule = $activity->model->rule;
                $template = $activity->template['template'];

                if (!isset($types[$rule]) || $template != $types[$rule]) {
                    continue;
                }
                if (!isset($categoryData[$rule])) {
                    $categoryData[$rule] = $activity->model->name;
                }
                $activityData[$rule][] = [
                    'id'         => $activity->id,
                    'title'      => $activity->name,
                    'slice_page' => $hostUrl . '/act/slice/' . $rule . '.html?act_id=' . $activity->id . '&noLogin=true',
                ];
            }
        }

        return [$categoryData, $activityData];
    }

    public function getVoteRecords($activity_id, $device_id, $vote_item, $begin_time, $end_time, $limit, $offset, $is_export = false)
    {
        if (!$activity_id) {
            return [0, []];
        }
        $voteCandidates = $this->voteCandidateService->getIdByActivityId($activity_id);
        $voteCandidateIds = Arr::flatten($voteCandidates->toArray());
        $query = DB::table('activities as a')
            ->select(['a.id', 'd.username', 'd.mobile', 'c.voted_at', 'b.title', 'c.ip', 'c.device_id', 'c.location'])
            ->leftJoin('vote_candidates as b', 'a.id', '=', 'b.activity_id')
            ->leftJoin('vote_records as c', 'b.id', '=', 'c.candidate_id')
            ->leftJoin('participants as d', 'c.uid', '=', 'd.uniqueid')
            ->where('a.id', "{$activity_id}")
            ->whereIn('c.candidate_id', $voteCandidateIds);
        if ($vote_item) {
            $query->where('b.title', '=', $vote_item);
        }
        if ($device_id) {
            $query->where('c.device_id', '=', $device_id);
        }
        if ($begin_time && $end_time) {
            $begin_time = strtotime($begin_time);
            $end_time = strtotime($end_time);
            $query->whereBetween('c.voted_at', [$begin_time, $end_time]);
        }
        $query->orderBy('c.voted_at', 'desc');
        //导出
        if ($is_export) {
            $res = $query->get()->toArray();

            return $res;
        }
        $limit = $limit ? $limit : 10;
        $offset = $offset > 0 ? $offset : 0;

        $count = $query->count();

        $query->limit($limit)->skip($offset);
        $res = $query->get();
        $res = $res ? $res : [];

        return ['total' => $count, 'rows' => $res];
    }

}